#ifndef SELECTION_HEADER_VIZMF_PROJECT
#define SELECTION_HEADER_VIZMF_PROJECT

#include <string>
#include <vector>
//#include <deque>
#include <iterator>
#include <map>
#include <algorithm>
#include <functional>

#include <src/core/workspace/molecule/molecule.h>   // includes also atom.h and bond.h as well as proper bond specification given in Molecule
#include <src/core/workspace/lattice.h>


/*
    VizMF UniformSelectionNode class

    Determines a pattern for a node of a uniform selection,
    which is a set of iterators/indices for one paticular Container instance.
*/

template <typename ContType, typename IndexType=ContType::iterator, typename ObjectType=ContType::value_type>
class UniformSelectionNode{
public:
    typedef ContType cont_type; // type of a container
    typedef IndexType index_type;   // a reference to value object
    typedef ObjectType value_type;  // type of an object, of which container is made

protected:
    typedef std::set<index_type> int_container_type;

public:
    typedef int_container_type::iterator ic_iterator;

public:
    UniformSelectionNode(const cont_type& C, index_type start, index_type finish)  // assuming initial range is continuous
        : cont_(C) //, start_(start), finish_(finish)
    {
        ic_iterator last = int_cont_.end();
        for(;start != finish; start++)
            last = int_cont_.insert(last, start);
    }

    template<typename Iterator>
    insert(Iterator beg, Iterator end){ // Iterator is iterator pointing to index_type
        int_cont_.insert(beg, end); // hoping the container is the same...
    }

    ic_iterator begin() const {return int_cont_.begin();}
    ic_iterator end() const {return int_cont_.end();}

    const cont_type& getContainer() const {return cont_;}  // shulga: could be eliminated in future

protected:
    const cont_type& cont_;
//    index_type start_;
//    index_type finish_;
    int_container_type int_cont_;
};

/*
    VizMF UniformSelection class

    Determines a pattern for a uniform selection, consisting of a set of UniformSelectionNode's.
    That enables iteration through both containers and selections associated to them.
*/

template<typename SelectionNode>
class UniformSelectionBase{
public:
    typedef SelectionNode selection_node_type;
    typedef selection_node_type::cont_type sn_cont_type;
    typedef unsigned int index_type;

private:
    typedef std::map<index_type, selection_node_type> cont_type;

public:
    typedef cont_type::iterator iterator;
    typedef cont_type::const_iterator const_iterator;

//public:
protected:
    UniformSelectionBase(){};

    // select all within the container via iterators of pair begin/end
    UniformSelectionBase(const sn_cont_type& C){
        sel_[C.number()] = selection_node_type(C, C.begin(), C.end());
    };

    // select all within the container via iterators of non-standard pair (not begin/end)
    UniformSelectionBase(const sn_cont_type& C, sn_cont_type::index_type beg, sn_cont_type::index_type end){
        sel_[C.number()] = selection_node_type(C, beg, end);
    };

    template <typename Iterator>
    UniformSelectionBase(Iterator beg, Iterator end){
        sel_(beg, end);
    }

    // shulga: optimal interface may subject to changes, but this one seems reasonable and sufficient

    // ---> stopped here...
/*
    void push_back(const selection_node_type& ls) {sel_.push_back(ls);};
    void push_front(const selection_node_type& ls) {sel_.push_front(ls);};
    void pop_back() {sel_.pop_back();};
    void pop_front() {sel_.pop_front();};
*/
    template <typename Iterator>
    insert (Iterator beg, Iterator end){
        sel_.insert(beg, end);
    }

    // access
    iterator begin() {return sel_.begin();};
    iterator end() {return sel_.end();};
    const_iterator begin() const {return sel_.begin();};
    const_iterator end() const {return sel_.end();};

protected:
    cont_type sel_;

public:
    UniformSelectionBase& operator+ (const UniformSelectionBase& usb){
        typedef selection_node_type::cont_ind_type ind_type;
        unsigned int !!!!/\/\/\/\/\/
        std::map< ind_type, std::bitset<

        UniformSelectionBase res(begin(), end());
        res.insert(usb.begin(), usb.end());
        return res;
    }
    UniformSelectionBase& operator- (const UniformSelectionBase& usb){}
    UniformSelectionBase& operator* (const UniformSelectionBase& usb){}
};

/*
    VizMF UniformSelectionIterator class

    Determines an iterator to traverse UniformSelection
*/

template<typename USelection, typename ObjectType=USelection::selection_node_type >
class UniformSelectionIterator : public std::bidirectional_iterator<ObjectType> {
public:
    typedef USelection sel_type;
    typedef ObjectType sel_node_type;
    typedef sel_node_type::value_type value_type;
    typedef UniformSelectionIterator<USelection, ObjectType> _Self;
    typedef sel_type::iterator outer_iterator;
    typedef value_type::index_type inner_iterator;

public:
    UniformSelectionIterator(sel_type * sel = 0) : ll_offset_() {
        if(!sel){
            // default constructors will do their job
        } else {
            sel_ = sel;
            hl_offset_ = sel->begin();
            if(hl_offset_ != sel_ -> end())
                ll_offset_ = hl_offset_ -> begin();
        }
    };

    _Self& operator++() {
        if(++ll_offset_ == hl_offset_ -> end()){
            hl_offset_++;
            ll_offset_ = hl_offset_ -> begin();
        }
        return *this;
    };

    _Self operator++(int) {
        _Self tmp = *this;
        ++(*this);  // make use of just defined prefix form of ++
        return tmp;
    };

    _Self& operator--() {
        if(ll_offset_ == hl_offset_ -> begin()){
            hl_offset_--;
            ll_offset_ = hl_offset_ -> end();
        } else ll_offset_--;
        return *this;
    };

    _Self operator--(int) {
        _Self tmp = *this;
        --(*this);  // make use of just defined prefix form of --
        return tmp;
    };

    value_type* operator->() const  // should 'const' be here?
    {
        return &(*ll_offset_);
    };

    value_type& operator*() const // should 'const' be here?
    {
        return *ll_offset_;
    };

    // experimental
    typedef sel_node_type::cont_ind_type    cont_ind_type;
    cont_ind_type getNodeContIndex(){return ll_offset_->getContIndex();}

    bool operator< (const _Self& other){
        if(this->getNodeContIndex() < other->getNodeContIndex()){
            return true;    // containers compared first
        } else if (other->getNodeContIndex() < this->getNodeContIndex()) {
            return false;
        } else if(this->ll_offset_ < other->ll_offset_)
            return true;
        return false;
    }


protected:
    sel_type * sel_;
    outer_iterator hl_offset_;  // high-level offset
    inner_iterator ll_offset_;  // low-level offset
};


/*
    VizMF UniformSelection class

    Determines a uniform selection with iterator
*/

template<typename SelectionNode, typename Iterator=UniformSelectionIterator <
                                                   UniformSelectionBase <SelectionNode> >
                                                   >
class UniformSelection : public UniformSelectionBase<SelectionNode> {
public:
    typedef SelectionNode selection_node_type;
    typedef Iterator iterator;
    typedef const Iterator const_iterator;    // not sure it is that easy
    typedef UniformSelectionBase<SelectionNode> Base;

public:
    UniformSelection(){};
    UniformSelection(const Base& b) : Base(b) {};

    iterator begin(){ return iterator (static_cast<::Base>(this) ); };
    iterator end(){ return iterator (); };
    const_iterator begin() const { return const_iterator (static_cast<::Base>(this) ); };
    const_iterator end() const { return const_iterator (); };

protected:
    //

public:
    UniformSelection& operator+ (const UniformSelection& us){

    }
    UniformSelection& operator- (const UniformSelection& us){}
    UniformSelection& operator* (const UniformSelection& us){}

};

// namespace _detail { //?
typedef UniformSelectionNode<Molecule, Molecule::atom_iterator, Molecule::atom_type> AtomSelectionNode;
typedef UniformSelectionNode<Molecule, Molecule::bond_iterator, Molecule::bond_type> BondSelectionNode;
typedef UniformSelectionNode<Lattice, Lattice::points_iterator, Lattice::point_type> GridSelectionNode;
//typedef UniformSelectionNode<Group, Lattice::points_iterator, Lattice::point_type> MoleculeSelectionNode;

typedef UniformSelection<AtomSelectionNode> atom_selection;
typedef UniformSelection<BondSelectionNode> bond_selection;
typedef UniformSelection<GridSelectionNode> node_selection;

// } // end of namespace

/*
  VizMF Selection class

  As for now (15.06.2010), Selection is a union of a predefined set of selections
*/

class Selection {
public:
  typedef ::atom_selection atom_sel_type;
  typedef ::bond_selection bond_sel_type;
  typedef ::node_selection node_sel_type;

  typedef atom_sel_type::iterator atom_leaf_iterator;
  typedef bond_sel_type::iterator bond_leaf_iterator;
  typedef node_sel_type::iterator node_leaf_iterator;

public:
  Selection() {}
  Selection(atom_sel_type atom_sel, bond_sel_type bond_sel, node_sel_type node_sel)
    : atom_sel_(atom_sel),  bond_sel_(bond_sel), node_sel_(node_sel) {}
//  Selection(const Selection& s) {}
  Selection(Workspace * wsp /*, std::string mask = "*:*:*" */) {
/*
  Selection should span objects in the workspace
  Select all should select all objects in the workspace
*/
  }

protected:
  void _select_all(){
// todo...
  }

protected:
  // AtomSelection
  // BondSelection
  // LatticeNodeSelection
  atom_sel_type atom_sel_;
  bond_sel_type bond_sel_;
  node_sel_type node_sel_;

public:
  // set union
  Selection& operator+ (const Selection& s){
      // simple and ineffective implementation

  }

  // set difference
  Selection& operator- (const Selection& s){}

  // set intersection
  Selection& operator* (const Selection& s){}
};


/*
todo:
======
1) where should transformation from string submasks to actual sets be done?
2) "select all" functionality
3) "select something" functionality
*/

#endif // SELECTION_HEADER_VIZMF_PROJECT


